#include "stm32f10x.h"
#include "usart.h"
#include <stdio.h>
#include <stdarg.h>
#include <math.h>


//环形 数组结构体实例化两个变量
UartBuf UartTxbuf;//环形发送结构体
UartBuf UartRxbuf;//环形接收结构体

unsigned char rx_buffer[RX_BUFFER_SIZE];
unsigned char tx_buffer[TX_BUFFER_SIZE];

void Usart_Init(uint32_t br_num)
{
    USART_InitTypeDef USART_InitStructure;
    USART_ClockInitTypeDef USART_ClockInitStruct;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //开启USART3时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);


    //配置PA9作为USART3　Tx
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //配置PA10作为USART3　Rx
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    USART_DeInit(USART3);
    //配置USART3
    //中断被屏蔽了
    USART_InitStructure.USART_BaudRate = br_num;       //波特率可以通过地面站配置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //8位数据
    USART_InitStructure.USART_StopBits = USART_StopBits_1;   //在帧结尾传输1个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;    //禁用奇偶校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;  //发送、接收使能
    //配置USART3时钟
    USART_ClockInitStruct.USART_Clock = USART_Clock_Disable;  //时钟低电平活动
    USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low;  //SLCK引脚上时钟输出的极性->低电平
    USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge;  //时钟第二个边沿进行数据捕获
    USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位数据的时钟脉冲不从SCLK输出

    USART_Init(USART3, &USART_InitStructure);
    USART_ClockInit(USART3, &USART_ClockInitStruct);


    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//使能USART3接收中断

    USART_Cmd(USART3, ENABLE);//使能USART3
}


#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
    x = x;
}
//重定义fputc函数
int fputc(int ch, FILE* f)
{
    USART_SendData(USART3, (unsigned char)ch);
    while (!(USART3->SR & USART_FLAG_TXE));
    return ch;
}
#endif


uint8_t TxBuffer[256];
uint8_t TxCounter = 0;
uint8_t count = 0;

void Usart_Put_Char(unsigned char Data)
{
    USART_SendData(USART3, (unsigned char)Data);
    while (!(USART3->SR & USART_FLAG_TXE));
}
void Usart_Put_Buf(unsigned char* DataToSend, uint8_t data_num)
{
    uint8_t i;
    for (i = 0; i < data_num; i++)
        Usart_Put_Char(*DataToSend++);
}


//读取环形数据中的一个字节
uint8_t UartBuf_RD(UartBuf* Ringbuf)
{
    uint8_t temp;
    temp = Ringbuf->pbuf[Ringbuf->Rd_Indx & Ringbuf->Mask];//数据长度掩码很重要，这是决定数据环形的关键
    Ringbuf->Rd_Indx++;//读取完成一次，读指针加1，为下一次 读取做 准备
    return temp;
}

void UartBuf_WD(UartBuf* Ringbuf, uint8_t DataIn)
{
    Ringbuf->pbuf[Ringbuf->Wd_Indx & Ringbuf->Mask] = DataIn;//数据长度掩码很重要，这是决定数据环形的关键
    Ringbuf->Wd_Indx++;//写完一次，写指针加1，为下一次写入做准备
}
//环形数据区的可用字节长度，当写指针写完一圈，追上了读指针
//那么证明数据写满了，此时应该增加缓冲区长度，或者缩短外围数据处理时间
uint16_t UartBuf_Cnt(UartBuf* Ringbuf)
{
    return (Ringbuf->Wd_Indx - Ringbuf->Rd_Indx) & Ringbuf->Mask;//数据长度掩码很重要，这是决定数据环形的关键
}

volatile uint8_t Udatatmp;//串口接收临时数据字节

void USART3_IRQHandler(void)
{
    if (USART_GetITStatus(USART3, USART_IT_TXE) != RESET)
    {
        USART_SendData(USART3, UartBuf_RD(&UartTxbuf)); //环形数据缓存发送
        if (UartBuf_Cnt(&UartTxbuf) == 0)  USART_ITConfig(USART3, USART_IT_TXE, DISABLE); //假如缓冲空了，就关闭串口发送中断
    }

    else if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {
        //此种环形缓冲数组串口接收方式，适用于解包各种数据，很方便。对数据的要求是:
        //发送方必须要求有数据包头，以便解决串口数据无地址的问题
        Udatatmp = USART_ReceiveData(USART3);          //临时数据赋值
        UartBuf_WD(&UartRxbuf, Udatatmp);              //写串口接收缓冲数组

        if (UartBuf_Cnt(&UartRxbuf) == 0) USART_SendData(USART3, 'E'); //串口接收数组长度等于0时，发送接收数组空标志
        if (UartBuf_Cnt(&UartRxbuf) == UartRxbuf.Mask) USART_SendData(USART3, 'F'); //串口接收数组长度等于掩码时，发送接收缓冲满标志
        USART_ClearITPendingBit(USART3, USART_IT_RXNE);//清除接收中断标志
    }
}



